package com.qs.rest.services;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.log4j.Logger;

import com.qs.entities.Channel;
import com.qs.entities.Feed;
import com.qs.entities.User;
import com.qs.entities.UserSession;
import com.qs.exceptions.ServiceException;
import com.qs.rest.IPrivateRestService;
import com.qs.services.FeedService;
import com.qs.services.SessionService;
import com.qs.services.UserService;
import com.qs.utils.HttpHeaderNames;
import com.qs.utils.HttpStatusCodes;
import com.qs.utils.HttpStatusStrings;
import com.qs.valuesobjects.ChannelVo;
import com.qs.valuesobjects.FeedVo;
import com.qs.valuesobjects.SessionVo;
import com.qs.valuesobjects.UserVo;
import com.qs.valuesobjects.containers.BaseContainerVo;
import com.qs.valuesobjects.containers.FeedContainerVo;
import com.qs.valuesobjects.containers.SessionContainerVo;
import com.qs.valuesobjects.containers.UserContainerVo;

public class PrivateRestServiceImpl extends BaseRestService implements IPrivateRestService{

	final static Logger log = Logger.getLogger(PrivateRestServiceImpl.class);
	
	private UserService 	userService;
	private SessionService 	sessionService;
	private FeedService 	feedService;
	
	@Context
	private HttpHeaders httpHeaders;
	
	@Context
	private Request httpRequest;
	
	@Context
	private ContainerRequestContext requestCtx;
	
	@Context
    private transient HttpServletRequest servletRequest;

	
	@Override
	public BaseContainerVo register(	String firstName,String lastName, String screenName, 
									String email, String password,String address, String phone, List<String> channelIds) {
		
		UserContainerVo userContainer = new UserContainerVo();
		try{
			
			User user = userService.createUser(firstName, lastName, screenName, email, password, address, phone,channelIds);
			
			userContainer.meta.code 		= HttpStatusCodes.OK;
			
			UserVo userVo 				= new UserVo();
			userVo.userId 				= user.userId;
			userVo.firstName 			= user.firstName;
			userVo.lastName 			= user.lastName;
			userVo.screenName   		= user.screenName;
			userVo.email				= user.email;
			//userVo.password				= user.password;
			userVo.address				= user.address;
			userVo.phone				= user.phone;
			userVo.createdOn			= user.createdOn.toString();
//			userVo.channels				= new ArrayList<ChannelVo>();
//			if(user.channels!=null && user.channels.size()>0){
//				for(Channel channel:user.channels){
//					ChannelVo channelVo = new ChannelVo();
//					channelVo.code = channel.code;
//					channelVo.name = channel.name;
//					//channelVo.orderIndex = channel.orderIndex.toString();
//					
//					userVo.channels.add(channelVo);
//				}
//			}

			userContainer.data 				= userVo;
			
			return userContainer;
			
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			userContainer.meta.code 	= HttpStatusCodes.INVALID_REQUEST;
			userContainer.meta.error 	= HttpStatusStrings.INVALID_REQUEST;
			userContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return userContainer;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			userContainer.meta.code 	= HttpStatusCodes.INTERNAL_SERVER_ERROR;
			userContainer.meta.error 	= HttpStatusStrings.INTERNAL_SERVER_ERROR;
			userContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return userContainer;
		}		
	}
	
	@Override
	public BaseContainerVo login(String email, String password) {
		
		SessionContainerVo sessionContainer = new SessionContainerVo();
		try{
			
			User 	user 	= userService.fetchUser(email, password);
			UserSession session = sessionService.createSession(user);
			user.isLogin = true;
			userService.updateUser(user);
			
			SessionVo sessionVo				= new SessionVo();
			sessionContainer.meta.code 	= HttpStatusCodes.OK;
			
			sessionVo.sessionId 		= session.sessionId;
			sessionVo.user				= new UserVo();
			sessionVo.user.userId		= session.user.userId;
			sessionVo.user.firstName	= session.user.firstName;
			sessionVo.user.lastName		= session.user.lastName;
			sessionVo.user.screenName 	= session.user.screenName;
			sessionVo.user.email		= session.user.email;
			sessionVo.user.address 		= session.user.address;
			sessionVo.user.phone 		= session.user.phone;
			sessionVo.user.createdOn	= session.user.createdOn.toString();
			sessionVo.lastAccessed		= session.lastAccessed.toString();
			sessionVo.isExpired			= session.isExpired.toString();
			sessionVo.createdOn			= session.createdOn.toString();
			
			sessionContainer.data		= sessionVo;
			
			
			return sessionContainer;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			sessionContainer.meta.code 		= HttpStatusCodes.INVALID_REQUEST;
			sessionContainer.meta.error 		= HttpStatusStrings.INVALID_REQUEST;
			sessionContainer.meta.details		= ExceptionUtils.getRootCause(exc) == null ? exc.toString() : ExceptionUtils.getRootCause(exc).toString();
			return sessionContainer;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			sessionContainer.meta.code 		= HttpStatusCodes.INTERNAL_SERVER_ERROR;
			sessionContainer.meta.error 		= HttpStatusStrings.INTERNAL_SERVER_ERROR;
			sessionContainer.meta.details		= ExceptionUtils.getRootCause(exc) == null ? exc.toString() : ExceptionUtils.getRootCause(exc).toString();
			return sessionContainer;
		}
	}
	
	@Override
	public BaseContainerVo createFeed(String channelId, String text) {
		FeedContainerVo feedContainer = new FeedContainerVo();
		try{
			
			UserSession session = (UserSession)servletRequest.getAttribute(HttpHeaderNames.USER_SESSION_OBJECT);
			Feed feed = feedService.createFeed(session.user.userId, channelId, text);
			
			feedContainer.meta.code = HttpStatusCodes.OK;
			feedContainer.data		= new FeedVo();
			feedContainer.data.text = text;
			feedContainer.data.createdOn = feed.createdOn.toString();
			return feedContainer;
			
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			feedContainer.meta.code 		= HttpStatusCodes.INVALID_REQUEST;
			feedContainer.meta.error 		= HttpStatusStrings.INVALID_REQUEST;
			feedContainer.meta.details		= ExceptionUtils.getRootCause(exc) == null ? exc.toString() : ExceptionUtils.getRootCause(exc).toString();
			return feedContainer;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			feedContainer.meta.code 		= HttpStatusCodes.INTERNAL_SERVER_ERROR;
			feedContainer.meta.error 		= HttpStatusStrings.INTERNAL_SERVER_ERROR;
			feedContainer.meta.details		= ExceptionUtils.getRootCause(exc) == null ? exc.toString() : ExceptionUtils.getRootCause(exc).toString();
			return feedContainer;
		}
		
	}
	

	@Override
	public BaseContainerVo logout() {
		SessionContainerVo sessionContainer = new SessionContainerVo();
		try{
			String sessionId 	= httpHeaders.getHeaderString( HttpHeaderNames.SESSION_ID );
			sessionService.updateUserSessionByExpiry(sessionId, true);
			sessionContainer.meta.code 	= HttpStatusCodes.OK;
			return sessionContainer;
			
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			sessionContainer.meta.code 		= HttpStatusCodes.INVALID_REQUEST;
			sessionContainer.meta.error 		= HttpStatusStrings.INVALID_REQUEST;
			sessionContainer.meta.details		= ExceptionUtils.getRootCause(exc) == null ? exc.toString() : ExceptionUtils.getRootCause(exc).toString();
			return sessionContainer;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			sessionContainer.meta.code 		= HttpStatusCodes.INTERNAL_SERVER_ERROR;
			sessionContainer.meta.error 		= HttpStatusStrings.INTERNAL_SERVER_ERROR;
			sessionContainer.meta.details		= ExceptionUtils.getRootCause(exc) == null ? exc.toString() : ExceptionUtils.getRootCause(exc).toString();
			return sessionContainer;
		}
	
	}

	
	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public void setSessionService(SessionService sessionService) {
		this.sessionService = sessionService;
	}
	
	public void setHeaders(HttpHeaders headers) {
		this.httpHeaders = headers;
	}

	public void setRequest(Request request) {
		this.httpRequest = request;
	}

	public void setFeedService(FeedService feedService) {
		this.feedService = feedService;
	}
	
	public void setRequestCtx(ContainerRequestContext requestCtx) {
		this.requestCtx = requestCtx;
	}
	
	public void setServletRequest(HttpServletRequest servletRequest) {
		this.servletRequest = servletRequest;
	}

	private Response.ResponseBuilder getNoCacheResponseBuilder( Response.Status status ) {
        CacheControl cc = new CacheControl();
        cc.setNoCache( true );
        cc.setMaxAge( -1 );
        cc.setMustRevalidate( true );
        return Response.status( status ).cacheControl( cc );
    }

	 

	  
}